#!/usr/bin/python
#
# Copyright (C) 2009 rambla.be
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
""" @file
@brief Implements RaseService.
"""

try:
  from xml.etree import cElementTree as ElementTree
except ImportError:
  try:
    import cElementTree as ElementTree
  except ImportError:
    from elementtree import ElementTree
import os
import urllib
import atom
import rawsc
import rawsc.service
from rawsc import rase
from rawsc.rase import port, wowsdp, mpegts, wowapp

SERVER_DEFAULT = "rase.str01.rambla.be"

class RaseService(rawsc.service.RawsService):
    """ @brief RaseService extends RawsService to provide an interface for RASE requests.
    """

    def __init__(self, username=None, password=None, source=None, server=SERVER_DEFAULT, port = None, additional_headers=None, handler=None):
        super(RaseService, self).__init__(username = username, password = password, source = source, server = server, port = port, additional_headers = additional_headers, handler = handler)

    def delete(self, uri):
        """ Deletes any resource, given the uri. """
        return self.Delete(uri = uri)

    def getPortFeed(self, query = None):
        """ Retrieves a port feed. 
        
            @param query rawsc.Query object that contains queryset args.
            @return PortFeed object
        """
        uri = "/port/"
        if query:
            query.feed = uri
            uri = query.ToUri()
        return self.Get(uri = uri, converter=rase.port.PortFeedFromString)

    def getPort(self, uri):
        """ Retrieves a port entry. 
        
            @param uri path (relative or absolute) to the port instance.
            @return PortEntry object
        """
        if uri is None:
          raise rawsc.RawscException('You must provide a valid URI argument to getPort().')
        return self.Get(uri, converter=rase.port.PortEntryFromString)
        
    def createPort(self, nr_of_ports, description=None):
        """ Claim ports (= POST /port/).

            @return PortEntry object
        """
        params = rase.port.PortParams(nr_of_ports=nr_of_ports, description=description)
        content = rase.port.PortContent(params = params)
        entry = rase.port.PortEntry(content = content)
        return self.Post(entry, uri= "/port/", converter= rase.port.PortEntryFromString)

    def updatePort(self, entry, uri = None):
        """ Update an existing port resource, using a PUT request.
        
            @param entry: the complete entry, containing the changed params
            @param uri location of the instance to be updated, if None it will be retrieved from the entry
        """
        if uri is None:
            uri = entry.id.text
        if not uri:
            raise rawsc.RawscException('Entry is not valid.')
        return self.Put(uri = uri, data = entry, converter = rase.port.PortEntryFromString)

    def getWowappFeed(self, query = None):
        """ Retrieves a wowapp feed. 

            @param query rawsc.Query object that contains queryset args.
            @return WowappFeed object
        """
        uri = "/wowapp/"
        if query:
            query.feed = uri
            uri = query.ToUri()
        return self.Get(uri = uri, converter=rase.wowapp.WowappFeedFromString)

    def getWowapp(self, uri):
        """ Retrieves a wowapp entry. 

            @param uri path (relative or absolute) to the wowapp instance.
            @return WowappEntry object
        """
        if uri is None:
          raise rawsc.RawscException('You must provide a valid URI argument to getWowapp().')
        return self.Get(uri, converter=rase.wowapp.WowappEntryFromString)


    def createWowsdp(self, filename, local_path):
        """ Tries to POST a new wowsdp resource to RASE.

            @param filename filename to be given to the uploaded file on the RASE server.
            @param local_path location of the file to be uploaded on the local machine

            @return WowsdpEntry object
        """
        media_source = rawsc.MediaSource(file_path = local_path, svr_filename = filename)
        media_entry = self.Post(data = None, uri = '/wowsdp/', media_source = media_source, converter=rase.wowsdp.WowsdpEntryFromString)
        return media_entry

    def getWowsdpFeed(self, query = None):
        """ Retrieves a wowsdp feed. 

            @param query rawsc.Query object that contains queryset args.
            @return WowsdpFeed object
        """
        uri = "/wowsdp/"
        if query:
            query.feed = uri
            uri = query.ToUri()
        return self.Get(uri = uri, converter=rase.wowsdp.WowsdpFeedFromString)

    def getWowsdp(self, uri):
        """ Retrieves a wowsdp entry. 

            @param uri path (relative or absolute) to the wowsdp instance.
            @return WowsdpEntry object
        """
        if uri is None:
          raise rawsc.RawscException('You must provide a valid URI argument to getWowsdp().')
        return self.Get(uri, converter=rase.wowsdp.WowsdpEntryFromString)

    def updateWowsdp(self, entry, uri = None):
        """ Update an existing wowsdp resource, using a PUT request.

            @param entry: the complete entry, containing the changed params
            @param uri location of the instance to be updated, if None it will be retrieved from the entry
        """
        if uri is None:
            uri = entry.id.text
        if not uri:
            raise rawsc.RawscException('Entry is not valid.')
        return self.Put(uri = uri, data = entry, converter = rase.wowsdp.WowsdpEntryFromString)

    def getWowsdpFile(self, uri, local_path = None):
        """ Downloads a transc file and (optionally) saves it to a local file location. 
        
            If local_path is given, an attempt is made to save the downloaded file and an exception is thrown in case of failure.
            If local_path is None, the downloaded file is not stored. The caller should store it himself using the file_handle attribute of the returned MediaSource object.
        
            @param uri path (relative or absolute) to the transc media item.
            @param local_path full path, including the filename, to a location where the downloaded file can be stored.
            @return rawsc.MediaSource object
        """
        if uri is None:
          raise rawsc.RawscException('You must provide a valid URI argument to getTranscFile().')
        return self.GetMedia(uri = uri, file_path = local_path)

    def createMpegts(self, wowapp, ip_address = None, description = None):
        """ Create a new mpegts resource by posting the params to RASE.

            @param wowapp : ID of the wowza application to be used for streaming
            @param ip_address : IP Address of the encoder

            @return MpegtsEntry object
        """
        params = rase.mpegts.MpegtsParams(wowapp=wowapp, ip_address=ip_address, description=description)
        content = rase.mpegts.MpegtsContent(params = params)
        entry = rase.mpegts.MpegtsEntry(content = content)
        return self.Post(entry, uri= "/mpegts/", converter= rase.mpegts.MpegtsEntryFromString)

    def getMpegts(self, uri):
        """ Retrieves a mpegts entry. 

            @param uri path (relative or absolute) to the mpegts instance.
            @return MpegtsEntry object
        """
        if uri is None:
          raise rawsc.RawscException('You must provide a valid URI argument to getMpegts().')
        return self.Get(uri, converter=rase.mpegts.MpegtsEntryFromString)

    def getMpegtsFeed(self, query = None):
        """ Retrieves a mpegts feed. 

            @param query rawsc.Query object that contains queryset args.
            @return MpegtsFeed object
        """
        uri = "/mpegts/"
        if query:
            query.feed = uri
            uri = query.ToUri()
        return self.Get(uri = uri, converter=rase.mpegts.MpegtsFeedFromString)

    def updateMpegts(self, entry, uri = None):
        """ Update an existing mpegts resource, using a PUT request.

            @param entry: the complete entry, containing the changed params
            @param uri location of the instance to be updated, if None it will be retrieved from the entry
        """
        if uri is None:
            uri = entry.id.text
        if not uri:
            raise rawsc.RawscException('Entry is not valid.')
        return self.Put(uri = uri, data = entry, converter = rase.mpegts.MpegtsEntryFromString)
